home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 176-200 / disk_177 / jask / jask.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  19KB  |  600 lines

  1. /* Copyright 1988 by I2(EYE) Systems.        JASK.C - Version 1.0
  2. *
  3. *      This file contains all of the routines for this program.
  4. *
  5. *
  6. *          JASK - Drop-in Intuitive Ask Replacement
  7. *
  8. *  This software may be freely distributed provided that this notice
  9. *  is retained.  It may be hacked or used as is in any product as long
  10. *  as you credit me for it.
  11. *
  12. *  If you find this program useful for enhancing your script file
  13. *  capabilites or as example source code, please send $5.00 to:
  14. *
  15. *            I2(EYE) Systems
  16. *            6620 Hunter Road
  17. *            Elkridge, MD 21227
  18. *            Attn: J. Barshinger
  19. *
  20. *    USENET or ARPANET: barsh@stsci
  21. *
  22. *    Note: if you send $10.00,  I'll send you the latest enhancements.
  23. *          Planned enhancements include a re-entrant version so
  24. *          that it can be made resident and a mouse-move capability
  25. *          that will automatically move the pointer to the default
  26. *          gadget.
  27. *
  28. *        JASK - Intuitive Ask Replacement
  29. *        --------------------------------
  30. *            
  31. *  JASK is a replacement for the ASK command distributed in the Amiga 1.3
  32. *  enhancer package. It will allow the user to click on a gadget to specify
  33. *  a positive or negative response rather than type it in at the keyboard.
  34. *  You can move the "requester" to the bottom of the screen or to the front
  35. *  or back of other screens if you don't want to answer it at the moment.
  36. *
  37. *            JASK Parameters
  38. *            ---------------
  39. *                
  40. *    -r  This parameter specifies the "requester" text.  This is
  41. *        the question you want to ask.
  42. *         
  43. *        This is the only REQUIRED parameter. (40 character max.)
  44. *
  45. *        EXAMPLE: "-rYour MOMMA is ?" = Your MOMMA is ? in the
  46. *                                       requester box.
  47. *        (put quotes around the string to put spaces in the text)
  48. *    
  49. *    -p  This specifies the text for the positive (left) gadget.
  50. *        When this gadget is selected, WARN (5) will be returned.
  51. *        (put quotes around the string to put spaces in the text)
  52. *        DEFAULT: YES    (12 character max.)
  53. *        EXAMPLE: -pUGLY = UGLY in the left gadget.
  54. *
  55. *    -n  This specifies the text for the negative (right) gadget.
  56. *        When this gadget is selected, 0 will be returned (success).
  57. *        (put quotes around the string to put spaces in the text)
  58. *        DEFAULT: NO        (12 character max.)
  59. *        EXAMPLE: -nPHAT = PHAT in the right gadget.
  60. *
  61. *    -t  This will specify a timeout period in seconds.  When the
  62. *        timeout period expires, the default answer will be returned.
  63. *        DEFAULT: wait forever
  64. *        EXAMPLE: -t10 = wait 10 seconds.
  65. *        
  66. *    -d  This parameter specifies which gadget is the default (safe)
  67. *        answer.  It does two things:
  68. *        a) determines if the positive or negative answer is 
  69. *           to be default.
  70. *        b) makes a more extravagant border for the specified
  71. *           gadget.
  72. *        n specifies the negative answer, p specifies the positive
  73. *        answer.
  74. *        DEFAULT: if this is not specified, both gadgets will look
  75. *                 the same, but the negative gadget will be returned.
  76. *        EXAMPLE: -dp = Fancy gadget rendered on positive and positive
  77. *                       is the default answer.
  78. *
  79. *    -q  This specifies whether you want the "requester" quick or if
  80. *        you want the "requester" to scroll up.
  81. *        DEFAULT: the "requester" scrolls up to it final position.
  82. *        EXAMPLE: -q = turn off the scrolling effects.
  83. *
  84. */
  85.  
  86. #include "exec/types.h"
  87. #include "intuition/intuition.h"
  88.  
  89. /* define ScreenFont1 to be the default Amiga font in Italic Mode     */
  90.  
  91. struct TextAttr ScreenFont1 = { "topaz.font", TOPAZ_EIGHTY, 
  92.                 FSF_ITALIC, FPF_ROMFONT };
  93.                 
  94. /* define ScreenFont2 to be the default Amiga font            */
  95.  
  96. struct TextAttr ScreenFont2 = { "topaz.font", TOPAZ_EIGHTY, 
  97.                 FS_NORMAL, FPF_ROMFONT };
  98.  
  99. #define POS_GAD TRUE        /* User value for the positive gadget    */
  100. #define NEG_GAD FALSE        /* User value for the negative gadget    */
  101.  
  102. /* Initialize the requester, positive gadget, and negative gadget text    */
  103.  
  104. char RText[] = "                                        ";
  105. char PText[] = "            ";
  106. char NText[] = "            ";
  107.  
  108. struct IntuiText ReqText = { /* Structure defining the Requester Text    */
  109.     3, 2,        /* front pen, back pen colors            */
  110.     JAM2,        /* front pen used for text, back for background */
  111.     0, 0,        /* LeftEdge, TopEdge offsets            */
  112.     &ScreenFont1,    /* Text font to use                */
  113.     RText,        /* Text to print                */
  114.     NULL };        /* Pointer to next Text structure        */
  115.  
  116. struct IntuiText ReqText1 = { /* Structure defining the PosGad Text    */
  117.     1, 2,        /* front pen, back pen colors            */
  118.     JAM1,        /* front pen used for text, back for background */
  119.     2, 5,        /* LeftEdge, TopEdge offsets            */
  120.     &ScreenFont2,    /* Text font to use                */
  121.     PText,        /* Text to print                */
  122.     NULL };        /* Pointer to next Text structure        */
  123.  
  124. struct IntuiText ReqText2 = { /* Structure defining the NegGad Text    */
  125.     1, 2,        /* front pen, back pen colors            */
  126.     JAM1,        /* front pen used for text, back for background */
  127.     2, 5,        /* LeftEdge, TopEdge offsets            */
  128.     &ScreenFont2,    /* Text font to use                */
  129.     NText,        /* Text to print                */
  130.     NULL };        /* Pointer to next Text structure        */
  131.  
  132. /* this data represents points offset from the actual gadget 
  133. (xy coordinates).  This puts the pen down at the first point and
  134. draws to the next point until done.  This is used to draw the boxes
  135. around the Gadgets                            */
  136.  
  137. short DefGadBorderPts[] = { 
  138.     -1, -6,        /* Starting point                */
  139.     -7, -1,        /* points to draw lines to...            */
  140.     -7, 20,
  141.     -1, 25,        /* This data defines the fancy gadget border     */
  142.     100, 25,    /* that you turn on with the -d parameter    */
  143.     106, 20,
  144.     106, -1,
  145.     100, -6,
  146.     -1, -6,
  147.     -1, 25,
  148.     -1, 20,
  149.     100, 20,
  150.     100, 25,
  151.     100, -6,
  152.     100, -1,
  153.     -1, -1 };
  154.     
  155. /* This data defines the inside box around the plain gadget border    */
  156.  
  157. short aGadBorderPts[] = {
  158.     -1, -1,        /* Starting point                */
  159.     100, -1,    /* points to draw the line to...        */
  160.     100, 20,
  161.     -1, 20,
  162.     -1, -1 };    /* interior gadget box outline             */
  163.  
  164. /* This data defines the outside boc around the plain gadget border    */
  165.  
  166. short bGadBorderPts[] = {
  167.     -4, -3,        /* Starting point                */
  168.     103, -3,    /* points to draw the line to...        */
  169.     103, 22,
  170.     -4, 22,
  171.     -4, -3 };    /* exterior gadget box outline             */
  172.  
  173. /* This structure points to the data defining the outside gadget border */
  174.  
  175. struct Border NormGadBorder = {
  176.     0, 0,        /* LeftEdge, TopEdge offsets from the gadget    */
  177.     2, 3, JAM1,    /* FrontPen, BackPen, Draw using the frontpen    */
  178.     5,        /* Number of xy coordinates in this border    */
  179.     bGadBorderPts,    /* pointer to the border xy coordinates        */
  180.     NULL };        /* pointer to the next border to draw        */
  181.  
  182. /* This structure defines the positive gadget border(s)            */
  183.  
  184. struct Border GadBorder1 = {
  185.     0, 0,        /* LeftEdge, TopEdge offsets from the gadget    */
  186.     2, 3, JAM1,    /* FrontPen, BackPen, Draw using the frontpen    */
  187.     5,        /* Number of xy coordinates in this border    */
  188.     aGadBorderPts,    /* pointer to the border xy coordinates        */
  189.     &NormGadBorder };/* pointer to the outside gadget border    */
  190.  
  191. /* This structure defines the negative gadget border(s)            */
  192.  
  193. struct Border GadBorder2 = {
  194.     0, 0,        /* LeftEdge, TopEdge offsets from the gadget    */
  195.     2, 3, JAM1,    /* FrontPen, BackPen, Draw using the frontpen    */
  196.     5,        /* Number of xy coordinates in this border    */
  197.     aGadBorderPts,    /* pointer to the border xy coordinates        */
  198.     &NormGadBorder };/* pointer to the outside gadget border    */
  199.  
  200. /* Structure defining the Negative Gadget                */
  201.  
  202. struct Gadget ReqGad2 = {
  203.     NULL,        /* pointer to next gadget            */
  204.     500, 10,     /* LeftEdge, TopEdge offsets within window     */
  205.     100, 20,    /* Width, Height of the gadget            */
  206.     GADGHCOMP,    /* Complement the gadget color when pressed    */
  207.     RELVERIFY,    /* Pointer must be in gadget when released    */
  208.     BOOLGADGET,    /* This is a boolean gadget            */
  209.     (APTR)(&GadBorder2), /* pointer to the gadget's borders        */
  210.     NULL,        /* pointer to image when gadget is selected    */
  211.     &ReqText2,    /* pointer to gadget's text            */
  212.     NULL, NULL,    /* Mutual exclude, special info flags        */
  213.     NEG_GAD,    /* User data defining gadget id            */
  214.     NULL };        /* Pointer to user data                */
  215.  
  216. /* Structure defining the Positive Gadget                */
  217.  
  218. struct Gadget ReqGad1 = {
  219.     &ReqGad2,    /* pointer to next gadget            */
  220.     40, 10,     /* LeftEdge, TopEdge offsets within window     */
  221.     100, 20,    /* Width, Height of the gadget            */
  222.     GADGHCOMP,    /* Complement the gadget color when pressed    */
  223.     RELVERIFY,    /* Pointer must be in gadget when released    */
  224.     BOOLGADGET,    /* This is a boolean gadget            */
  225.     (APTR)(&GadBorder1), /* pointer to the gadget's borders        */
  226.     NULL,        /* pointer to image when gadget is selected    */
  227.     &ReqText1,    /* pointer to gadget's text            */
  228.     NULL, NULL,    /* Mutual exclude, special info flags        */
  229.     POS_GAD,    /* User data defining gadget id            */
  230.     NULL };        /* Pointer to user data                */
  231.  
  232. /* Structure defining the Screen                    */
  233.  
  234. struct NewScreen ReqScreen = {
  235.     0, 210,          /* LeftEdge, TopEdge                 */
  236.     640, 53,     /* Width, Height                 */
  237.     2,        /* Depth - number of bit-planes            */
  238.     2, 3,          /* DetailPen, BlockPen                 */
  239.     HIRES,          /* ViewModes - 640X200                */
  240.     CUSTOMSCREEN,      /* Screen Type                     */
  241.     &ScreenFont2,     /* Default Font                    */
  242.     "JRBII's Ask Requester V1.0", /* Default Title              */
  243.     NULL,         /* Gadgets, currently ignored             */
  244.     NULL };        /* Custom Bit Map                */
  245.  
  246. /* Structure defining the Window                    */
  247.  
  248. struct NewWindow ReqWindow = {
  249.     0, 10,         /* LeftEdge, TopEdge offset within screen    */
  250.     640, 43,    /* Width, Height                 */ 
  251.     -1, -1,       /* DetailPen, BlockPen, -1 means same as screen */
  252.     GADGETUP,    /* IDCMP Flags, send message on Gadget selected */
  253.     ACTIVATE,     /* Window Flags - Activate the window          */
  254.     &ReqGad1,    /* Pointer to FirstGadget in window        */
  255.     NULL,        /* CheckMark                       */
  256.     NULL,         /* Window title                 */
  257.     NULL,        /* Pointer to Screen                 */
  258.     NULL,        /* Pointer to BitMap                 */
  259.     0, 0,        /* Minimum width, Minimum height         */
  260.     0, 0,        /* Maximum width, Maximum height         */
  261.     CUSTOMSCREEN }; /* Screen Type for this Window             */
  262.  
  263.     struct Window *ReqWin = NULL; /* pointer to a Window structure  */
  264.     struct Screen *ReqScr = NULL; /* pointer to a Screen structure  */
  265.  
  266.     struct Window *OpenWindow();  /* define the OpenWindow routine    */
  267.     struct Screen *OpenScreen();  /* define the OpenScreen routine    */
  268.  
  269.     LONG IntuitionBase = NULL;    /* Address of Intuition library    */
  270.                       /* IT MUST BE A GLOBAL SYMBOL    */
  271.  
  272.     LONG result;          /* result returned to the script file    */
  273.     int timeout;          /* number of seconds before timeout    */
  274.     struct IntuiMessage *msg; /* Message pointer for msg received    */
  275.                   /* from the IDCMP.            */
  276.  
  277.  
  278. /* This routine cleans up and returns "result" to AmigaDos.  It is    */
  279. /* called for normal termination of the program, in addition to any    */
  280. /* error conditions encountered.                    */
  281.  
  282. void Done()
  283. {
  284.  
  285.     /* if there is a message leftover, return it to Intuition    */
  286.  
  287.     if (msg != 0) ReplyMsg(msg);
  288.  
  289.     /* if the Window exists, close it                */
  290.  
  291.     if (ReqWin != NULL) CloseWindow(ReqWin);
  292.  
  293.     /* if the Screen is open, close it                */
  294.  
  295.     if (ReqScr != NULL) CloseScreen(ReqScr);
  296.  
  297.     /* if the Intuition library is open, close it            */
  298.  
  299.     if (IntuitionBase != NULL) CloseLibrary(IntuitionBase);
  300.  
  301.     /* return result to AmigaDos                    */
  302.  
  303.     exit(result);
  304.  
  305. } /* end Done() */
  306.  
  307.  
  308. /* This routine parses the command line parameters and sets up the    */
  309. /* requested special effects                        */
  310. /* Parsing and error checking has been kept to a minimum here to    */
  311. /* keep the executable code size as small as possible            */
  312.  
  313. void Parse_Args(argc, argv)
  314. int argc;    /* count of parameters passed                */
  315. char *argv[];    /* pointer to the parameters                */
  316. {
  317.     char i, k, x, y, error, rfound, pfound, nfound, *arg;
  318.     
  319.     error = 0;    /* error counter                */
  320.     rfound = FALSE; /* -r parameter found?, it's a required parm    */
  321.     pfound = FALSE; /* -p parameter found?                */
  322.     nfound = FALSE; /* -n parameter found?                */
  323.     
  324.     for (i=1; i<argc; i++) /* go through all the parameters        */
  325.     {
  326.         arg = argv[i]; /* get pointer to the current parameter    */
  327.         
  328.         if (arg[0] != '-') error++; /* make sure there's a dash */
  329.         
  330.         /* determine which parameter this is            */
  331.  
  332.         switch (tolower(arg[1])) /* convert the char to lower    */
  333.         {
  334.  
  335.         case 'q':        /* quick parameter        */
  336.             ReqScreen.TopEdge = 146; /* put the screen in    */
  337.                          /* its final location    */
  338.             break;
  339.  
  340.         case 'r':        /* requester text parmeter    */
  341.             if (!rfound)
  342.             {
  343.               rfound = TRUE;  /* set -r parm found flag    */
  344.  
  345.               /* if parm text is greater than its max size     */
  346.               /* truncate it to max size, save the size in k*/
  347.               if ((k = strlen(&arg[2])) > 40)
  348.                 k = 40;
  349.  
  350.               /* calculate the number of spaces needed to    */
  351.               /* center the text in the requester        */
  352.               x = (40 - k) / 2;
  353.             
  354.               /* copy the text into the requester text array */
  355.               for (y = 2; y < k+2; x++, y++)
  356.                 RText[x] = arg[y];
  357.             };
  358.             
  359.             break;
  360.             
  361.         case 'p':        /* Positive Gadget text parm    */
  362.             if (!pfound)
  363.             {
  364.               pfound = TRUE;  /* set -p parm found flag    */
  365.  
  366.               /* if input text is greater than its max size */
  367.               /* truncate it to max size, save the size in k*/
  368.               if ((k = strlen(&arg[2])) > 12)
  369.                 k = 12;
  370.  
  371.               /* calculate the number of spaces needed to    */
  372.               /* center the text in the Gadget        */
  373.               x = (12 - k) / 2;
  374.             
  375.               /* copy the text into the PosGad text array    */
  376.               for (y = 2; y < k+2; x++, y++)
  377.                 PText[x] = arg[y];
  378.             };
  379.             
  380.             break;
  381.  
  382.         case 'n':        /* Negative Gadget text parm    */
  383.             if (!nfound)
  384.             {
  385.               nfound = TRUE;  /* set -n parm found flag    */
  386.  
  387.               /* if input text is greater than its max size     */
  388.               /* truncate it to max size, save the size in k    */
  389.               if ((k = strlen(&arg[2])) > 12)
  390.                 k = 12;
  391.  
  392.               /* calculate the number of spaces needed to    */
  393.               /* center the text in the Gadget        */
  394.               x = (12 - k) / 2;
  395.             
  396.               /* copy the text into the NegGad text array    */
  397.               for (y = 2; y < k+2; x++, y++)
  398.                 NText[x] = arg[y];
  399.             };
  400.  
  401.             break;
  402.  
  403.         case 't':        /* Timeout parameter        */
  404.  
  405.             /* convert the string to an integer value    */
  406.             stcd_i(&arg[2],&timeout);
  407.  
  408.             timeout *= 10; /* our clock ticks 10 times per     */
  409.                        /* second, so multiply the    */
  410.                        /* timeout by 10 to get seconds    */
  411.  
  412.             /* Cause the IDCMP to get a timer message    */
  413.             /* 10 times per second in addition to receiving */
  414.             /* gadget selection messages            */
  415.             ReqWindow.IDCMPFlags = GADGETUP|INTUITICKS;
  416.             break;
  417.  
  418.         case 'd':        /* Default specifier parm    */
  419.             if (tolower(arg[2]) == 'n')
  420.             { /* Negative Gadget Specified             */
  421.                 /* Setup the gadget border to use the    */
  422.                 /* fancy border                */
  423.                 GadBorder2.Count = 16; /* 16 xy points    */
  424.                 GadBorder2.XY = DefGadBorderPts; 
  425.                 GadBorder2.NextBorder = NULL;
  426.                 result = 0; /* default result is Neg    */
  427.             }
  428.             else if (tolower(arg[2]) == 'p') 
  429.             { /* Pos Gadget specified             */
  430.                 /* Setup the gadget border to use the     */
  431.                 /* fancy border                */
  432.                 GadBorder1.Count = 16; /* 16 xy points  */
  433.                 GadBorder1.XY = DefGadBorderPts;
  434.                 GadBorder1.NextBorder = NULL;
  435.                 result = 5; /* default result is Pos    */
  436.             }
  437.             else error++; /* anything except 0 or 1 is err    */
  438.             break;
  439.  
  440.         default: /* Any other parameters specifiers are wrong    */
  441.             error++;
  442.             break;
  443.  
  444.         }; /* end switch */
  445.  
  446.     }; /* end for */
  447.     
  448.     if (!pfound)    /* if pos text not specified, just say YES    */
  449.     {
  450.         PText[4] = 'Y';
  451.         PText[5] = 'E';
  452.         PText[6] = 'S';
  453.     };            
  454.  
  455.     if (!nfound)    /* if neg text not specified, just say NO    */
  456.     {
  457.         NText[5] = 'N';
  458.         NText[6] = 'O';
  459.     };            
  460.  
  461.     if (error || (!rfound)) /* if an error occurred...        */
  462.     {
  463.         /* print the usage message                */
  464.         puts("USAGE: jask -r [-q] [-p] [-n] [-t] [-d]");
  465.         exit(10);    /* and exit back to AmigaDos        */
  466.     };
  467.     
  468. } /* end Parse_Args() */
  469.  
  470.  
  471. void main(argc, argv)
  472. int argc;
  473. char *argv[];
  474. {
  475.     struct Gadget *Gad; /* pointer to the Gadget message        */
  476.     short GadID;        /* Gadget ID for the message        */
  477.     int time;        /* number of ticks since program start    */
  478.     char i;
  479.     
  480.     time = 0;        /* initialize time to 0            */
  481.     result = 0;        /* default result is 0, if not specified    */
  482.  
  483.     Parse_Args(argc, argv); /* Parse the command line parameters    */
  484.  
  485.     /* Open the intuition library, on error exit...            */
  486.  
  487.     if ((IntuitionBase = OpenLibrary("intuition.library",0)) == NULL)
  488.     {
  489.         puts("Error opening the intuition library");
  490.         exit(10);
  491.     };
  492.     
  493.     /* Open the Screen, on error call done to also close the    */
  494.     /* intuition library                        */
  495.  
  496.     if ((ReqScr = OpenScreen(&ReqScreen)) == NULL)
  497.     {
  498.         puts("Can't open ReqScreen\n");
  499.         result = 10;
  500.         Done();
  501.     };
  502.  
  503.     ReqWindow.Screen = ReqScr;    /* Put the screen address in    */
  504.                     /* window structure, so the    */
  505.                     /* window knows where to go    */
  506.  
  507.     /* Open the window, on error call done to close the screen and    */
  508.     /* the intuition library                    */
  509.  
  510.     if ((ReqWin = OpenWindow(&ReqWindow)) == NULL)
  511.     {
  512.         puts("Can't open ReqWindow\n");
  513.         result = 10;
  514.         Done();
  515.     };
  516.  
  517.     /* Print the requester text into the window at x=160, y=15    */
  518.  
  519.     PrintIText(ReqWin->RPort,&ReqText,160,15);
  520.  
  521.     /* Scroll the screen up to its final position, unless the -q    */
  522.     /* option was specified, which automatically puts it in its    */
  523.     /* final position                        */
  524.  
  525.     for (i=0; ((i<64) && (ReqScreen.TopEdge > 200)) ; i++)
  526.         MoveScreen(ReqScr, 0, -1);
  527.  
  528.     while(TRUE)    /* loop forever, exit on GADGETUP or timeout    */
  529.     {
  530.  
  531.         /* Wait for an intuition message from the window's port    */
  532.         
  533.         WaitPort( ReqWin->UserPort );  
  534.  
  535.         /* Message received, so get a pointer to it        */
  536.  
  537.         msg = (struct IntuiMessage *) GetMsg(ReqWin->UserPort);
  538.  
  539.         /* We could recieve more that one message, so loop    */
  540.         /* until all have been processed            */
  541.  
  542.         while (msg != 0)
  543.         {
  544.             
  545.             /* switch on the type of message received    */
  546.             
  547.             switch (msg->Class)
  548.             {
  549.             case GADGETUP:    /* A Gadget was selected    */
  550.  
  551.                 /* Get the address of the Gadget    */
  552.  
  553.                 Gad = (struct Gadget *)(msg->IAddress);
  554.  
  555.                 /* Determine which gadget was selected    */
  556.  
  557.                 GadID = Gad->GadgetID;
  558.  
  559.                 /* if GadID is TRUE, the pos gadget was    */
  560.                 /* selected, else the neg was selected    */
  561.                 /* set the result appropriately        */
  562.  
  563.                 if (GadID)
  564.                     result = 5;
  565.                 else
  566.                     result = 0;
  567.  
  568.                 /* We're done, close whatever we opened    */
  569.                 /* and return the result to AmigaDos    */
  570.  
  571.                 Done();
  572.                 break;
  573.  
  574.             case INTUITICKS: /* A timer msg was received    */
  575.  
  576.                 /* if the tick count is greater than    */
  577.                 /* timeout, we're done, so close what-    */
  578.                 /* ever we opened and send the default    */
  579.                 /* result to AmigaDos            */
  580.  
  581.                 if (time++ > timeout) Done();
  582.                 break;
  583.             } /* switch (msg->class)... */
  584.  
  585.             ReplyMsg(msg); /* Done with the msg, so send it    */
  586.                        /* back to intuition        */
  587.  
  588.             /* Get the next message, if any            */
  589.  
  590.             msg = (struct IntuiMessage *) 
  591.                 GetMsg(ReqWin->UserPort);
  592.                   
  593.         } /* end while (msg != 0)... */
  594.  
  595.     } /* end while (TRUE)... */
  596.  
  597. } /* end main() */
  598.  
  599. /* End of file - JASK.C                            */
  600.